﻿

'*******************************************************************
' Program: Data Center Visio Rack Tool
' Author: Albert E Edlund
' Date:
'
' Purpose: draw data
'
'
'*******************************************************************

Imports System.Runtime.InteropServices
Imports Microsoft.Office.Interop.Visio

Imports Microsoft.Practices.EnterpriseLibrary.Common
Imports Microsoft.Practices.EnterpriseLibrary.Data
Imports Microsoft.Practices.EnterpriseLibrary.ExceptionHandling

Imports visRackSysMgmt
Imports visRackSysMgmt.clsDC_RackData
Imports visRackSysMgmt.dc_Product
Imports visRackSysMgmt.dc_Link
Imports visRackSysMgmt.dc_Network



Imports System
Imports System.ComponentModel
Imports System.Collections.Generic
Imports System.Collections.ObjectModel

Imports System.Data
Imports System.Drawing
Imports System.Windows.Forms

Imports System.IO


Public Class clsExampleDraw


#Region " Properties and declarations "

    '
    ' we use page dictionaries to reduce the time to find a visio shape by
    ' eliminating the time it takes to go to visio. 
    '
    Private m_dictComponents As Dictionary(Of Integer, String)
    Public Property dictComponents() As Dictionary(Of Integer, String)
        Get
            If m_dictComponents Is Nothing Then
                m_dictComponents = New Dictionary(Of Integer, String)
            End If
            dictComponents = m_dictComponents
        End Get
        Set(ByVal value As Dictionary(Of Integer, String))
            m_dictComponents = value
        End Set
    End Property

    Private m_dictLinks As Dictionary(Of Integer, String)
    Public Property dictLinks() As Dictionary(Of Integer, String)
        Get
            If m_dictLinks Is Nothing Then
                m_dictLinks = New Dictionary(Of Integer, String)
            End If
            dictLinks = m_dictLinks
        End Get
        Set(ByVal value As Dictionary(Of Integer, String))
            m_dictLinks = value
        End Set
    End Property



    '********* visio snippet vb.net visXXXX ******************
    Private _drawingApplication As Microsoft.Office.Interop.Visio.Application
    Public Property drawingApplication() As Microsoft.Office.Interop.Visio.Application
        Get
            Return Me._drawingApplication
        End Get
        Set(ByVal value As Microsoft.Office.Interop.Visio.Application)
            If (value Is Nothing) Then
                Throw New System.ArgumentNullException("ApplicationValueIsNull", _
                    "drawingApplication is Null.")
            End If
            Me._drawingApplication = value
        End Set
    End Property


    '********* visio snippet vb.net visXXXX ******************
    Private _drawingDocument As Microsoft.Office.Interop.Visio.Document
    Public Property drawingDocument() As Microsoft.Office.Interop.Visio.Document
        Get
            Return Me._drawingDocument
        End Get
        Set(ByVal value As Microsoft.Office.Interop.Visio.Document)
            If (value Is Nothing) Then
                Throw New System.ArgumentNullException("DocumentValueIsNull", _
                    "drawingDocument is Null.")
            End If
            Me._drawingDocument = value
        End Set
    End Property


    '********* visio snippet vb.net visXXXX ******************
    Private _drawingPage As Microsoft.Office.Interop.Visio.Page
    Public Property drawingPage() As Microsoft.Office.Interop.Visio.Page
        Get
            Return Me._drawingPage
        End Get
        Set(ByVal value As Microsoft.Office.Interop.Visio.Page)
            If (value Is Nothing) Then
                Throw New System.ArgumentNullException("PageValueIsNull", _
                    "drawingPage is Null.")
            End If
            Me._drawingPage = value
        End Set
    End Property

    '
    ' custom stencils 
    '
    Public m_customstencilpath As String = My.Settings.path_custom_stencils
    Public Property _CustomStencilPath() As String
        Get
            Return Me.m_customstencilpath
        End Get
        Set(ByVal value As String)
            Me.m_customstencilpath = value
        End Set
    End Property

    '
    ' visio helpers
    '
    Private m_clsVisio As clsVisioSupport
    Public Property _clsVisio() As clsVisioSupport
        Get
            Return Me.m_clsVisio
        End Get
        Set(ByVal value As clsVisioSupport)
            Me.m_clsVisio = value
        End Set
    End Property


    Private Structure stcUniqueLink
        Public NodeA As String
        Public NodeAPort As String
        Public NodeB As String
        Public NodeBPort As String
        Public Type As Int16
        Public SubType As Int16
    End Structure

    Private Sub initLkUnique(ByRef lkUnique As stcUniqueLink)
        With lkUnique
            .NodeA = ""
            .NodeAPort = ""
            .NodeB = ""
            .NodeBPort = ""
            .Type = dc_Product.vnetType.ptNetworkLink
            .SubType = dc_Link.enumLinkTypes.linkCopper
        End With
    End Sub

#End Region

#Region " Constructor "



    Public Sub New(ByVal visApplication As Microsoft.Office.Interop.Visio.Application, _
                   ByVal visDocument As Microsoft.Office.Interop.Visio.Document, _
                   ByVal visPage As Microsoft.Office.Interop.Visio.Page)


        drawingApplication = visApplication
        drawingDocument = visDocument
        drawingPage = visPage

        If _clsVisio Is Nothing Then
            _clsVisio = New clsVisioSupport
        End If


    End Sub


#End Region

#Region " Example Drawing "

    '
    '
    '
    Public Sub drawExampleRack()

        If Me.drawingApplication Is Nothing Then Exit Sub


        Dim m_clsNet As clsAttrNetwork = New clsAttrNetwork(drawingApplication, drawingDocument)
        Dim m_clsComp As clsComponents = New clsComponents(drawingApplication, drawingDocument)

        Try

            Dim visPage As Microsoft.Office.Interop.Visio.Page = Nothing
            Dim visPageSheet As Microsoft.Office.Interop.Visio.Shape = Nothing
            Dim visCell As Microsoft.Office.Interop.Visio.Cell = Nothing
            Dim stnDoc As Microsoft.Office.Interop.Visio.Document = Nothing
            Dim mstShape As Microsoft.Office.Interop.Visio.Master = Nothing
            Dim devShape As Microsoft.Office.Interop.Visio.Shape = Nothing
            Dim strLayer As String = dc_Network.netStatus.netUndefined.ToString

            ' the components that we want to work with
            Dim strRack As String = "CommRack"
            Dim strRouter As String = "Router"
            Dim strAppSrv As String = "AppSrv"
            Dim strFileSrv As String = "FileSrv"
            Dim strRaidArray As String = "Raid Array"

            ' we will use the component class dataset/datatable as our target for
            ' the datarows that we need for transferring shapedata to our examples
            m_clsComp.initDataSetAndTable()
            ' drTemp will be our work record
            Dim drTemp As System.Data.DataRow = Nothing

            ' if we do not have a page then add one to the drawing
            If drawingPage Is Nothing Then
                drawingPage = drawingDocument.Pages.Add
                drawingPage.Name = "Test Rack"
            End If
            _clsVisio.drawingPage = drawingPage
            m_clsNet.drawingPage = drawingPage


            visPageSheet = drawingPage.PageSheet

            ' so that we can color code device status
            ' go add some layers to the page
            AddNetworkLayersToPage(drawingPage)

            '
            ' have to setup the page scaling
            ' page width and height may be different between production and example
            ' because the production page has to be able to handle both a row and a single rack
            '
            visCell = visPageSheet.Cells("DrawingScale")
            _clsVisio.SetCellValueToString(visCell, My.Settings.drwDrawingScale)
            visCell = visPageSheet.Cells("PageScale")
            _clsVisio.SetCellValueToString(visCell, My.Settings.drwPageScaleSingle)
            visCell = visPageSheet.Cells("DrawingScaleType")
            _clsVisio.SetCellValueToString(visCell, My.Settings.drwDrawingScale)

            visCell = visPageSheet.Cells("PageWidth")
            _clsVisio.SetCellValueToString(visCell, My.Settings.drwPageWidthSingle)
            visCell = visPageSheet.Cells("PageHeight")
            _clsVisio.SetCellValueToString(visCell, My.Settings.drwPageHeightSingle)

            ' route the lines directly instead of right angle
            visPageSheet.Cells("RouteStyle").Formula = "1"


            'now that we have the location information
            ' go add the property boxes to the page
            Dim myArray As Object
            myArray = _clsVisio.InitPageFieldsSimple("TestRack")
            _clsVisio.AddArrayPropertyBoxesToPage( _
                    drawingPage, myArray)


            ' we only load the rack stencil for this example
            stnDoc = drawingApplication.Documents.OpenEx(My.Settings.rack_stencil, _
                                VisOpenSaveArgs.visOpenDocked + VisOpenSaveArgs.visOpenHidden)

            '*******************************************************************
            ' install a rack
            mstShape = stnDoc.Masters("Rack")
            devShape = drawingPage.Drop(mstShape, 0, 0)
            ' put it over on the right so we have the text fields
            visCell = devShape.Cells("pinX")
            _clsVisio.SetCellValueToString(visCell, "5.5 ft")
            ' put it above the floor line about a foot
            visCell = devShape.Cells("pinY")
            _clsVisio.SetCellValueToString(visCell, "0.75 ft")
            devShape.NameU = strRack
            devShape.Name = strRack
            devShape.Text = strRack
            ' for generic rack we do not delete shape data because we need the 
            ' rack addin
            '_clsVisio.deleteShapeData(devShape)

            ' put in the basic custom properties
            m_clsComp.m_dc.initProperties()
            m_clsComp.m_dc.compView = dc_Product.View.viewFront
            m_clsComp.m_dc.compName = devShape.Name
            m_clsComp.m_dc.compType = dc_Product.vnetType.ptNetworkPassive
            m_clsComp.m_dc.compSubtype = dc_Product.vnetSubtype.stRack

            drTemp = m_clsComp.m_dt.NewRow
            m_clsComp.movePropertiesToDataRow(drTemp, m_clsComp.m_dc)
            m_clsComp.UpdateComponentProperties(devShape, drTemp)
            drTemp = Nothing

            ' the connection points aren't really friendly so we 'name' them
            RenameRackShelfRows(devShape)

            visCell = devShape.Cells("prop.ucount")
            ' a tall rack so give it enough slots
            _clsVisio.SetCellValueToString(visCell, "42")

            ' when we add the rack to the page, it adds a user cell to the
            ' page sheet that we want to turn off
            If visPageSheet.CellExists("user.showu", False) = True Then
                visCell = visPageSheet.Cells("user.showu")
                visCell.FormulaU = "False"
            End If
            ' assign it to the cabinets layer
            _clsVisio.addShapeToLayer(drawingPage, devShape, "Cabinets", 0)

            '*******************************************************************
            ' put a router on the page
            mstShape = stnDoc.Masters("Router 2")
            devShape = drawingPage.Drop(mstShape, 0, 0)
            devShape.NameU = strRouter
            devShape.Name = strRouter
            devShape.Text = strRouter
            _clsVisio.deleteShapeData(devShape)

            ' put it in slot 30 using the naming we built above for the rack
            InstallComponentInSlot( _
                drawingPage, strRack, strRouter, 30)
            ' since it is a generic shape add some connection points to it
            _clsVisio.AddStandardConnections(devShape)
            ' assign it to the default layer
            _clsVisio.addShapeToLayer(drawingPage, devShape, strLayer, 0)
            ' add the custom properties
            m_clsComp.m_dc.initProperties()
            m_clsComp.m_dc.compView = dc_Product.View.viewFront
            m_clsComp.m_dc.compName = devShape.Name
            m_clsComp.m_dc.compType = dc_Product.vnetType.ptNetworkActive
            m_clsComp.m_dc.compSubtype = dc_Product.vnetSubtype.stRouter

            drTemp = m_clsComp.m_dt.NewRow
            m_clsComp.movePropertiesToDataRow(drTemp, m_clsComp.m_dc)
            m_clsComp.UpdateComponentProperties(devShape, drTemp)
            drTemp = Nothing

            ' give it a loopback address for testing
            m_clsNet.m_dc.initProperties()
            m_clsNet.UpdateNetworkProperties(devShape, Nothing, "addattr")
            ' default test address is loopback 127.0.0.1
            devShape.Cells("prop.attrnetipaddress").FormulaU = _clsVisio.StringToFormulaForString("127.0.0.1")
            devShape.Cells("prop.attrnetnetworkname").FormulaU = _clsVisio.StringToFormulaForString(devShape.Name)

            '*******************************************************************
            '  now install a file server
            mstShape = stnDoc.Masters("Standalone File Storage")
            devShape = drawingPage.Drop(mstShape, 0, 0)
            devShape.NameU = strFileSrv
            devShape.Name = strFileSrv
            devShape.Text = strFileSrv
            _clsVisio.deleteShapeData(devShape)

            InstallComponentInSlot( _
                drawingPage, strRack, strFileSrv, 20)
            m_clsComp.m_dc.initProperties()
            m_clsComp.m_dc.compView = dc_Product.View.viewFront
            m_clsComp.m_dc.compName = devShape.Name
            m_clsComp.m_dc.compType = dc_Product.vnetType.ptPlatformWintel
            m_clsComp.m_dc.compSubtype = dc_Product.vnetSubtype.stWintelServer

            drTemp = m_clsComp.m_dt.NewRow
            m_clsComp.movePropertiesToDataRow(drTemp, m_clsComp.m_dc)
            m_clsComp.UpdateComponentProperties(devShape, drTemp)
            drTemp = Nothing


            m_clsNet.m_dc.initProperties()
            ' test for blocked frame size (yahoo site)
            m_clsNet.UpdateNetworkProperties(devShape, Nothing, "addattr")
            ' test yahoo site
            devShape.Cells("prop.attrnetipaddress").FormulaU = _clsVisio.StringToFormulaForString("69.147.126.65")
            devShape.Cells("prop.attrnetnetworkname").FormulaU = _clsVisio.StringToFormulaForString(devShape.Name)


            _clsVisio.addShapeToLayer(drawingPage, devShape, strLayer, 0)
            _clsVisio.AddStandardConnections(devShape)

            '*******************************************************************
            ' then an application server
            mstShape = stnDoc.Masters("Server")
            devShape = drawingPage.Drop(mstShape, 0, 0)
            devShape.NameU = strAppSrv
            devShape.Name = strAppSrv
            devShape.Text = strAppSrv
            _clsVisio.deleteShapeData(devShape)

            InstallComponentInSlot(drawingPage, strRack, strAppSrv, 10)
            _clsVisio.addShapeToLayer(drawingPage, devShape, strLayer, 0)
            _clsVisio.AddStandardConnections(devShape)

            m_clsComp.m_dc.initProperties()
            m_clsComp.m_dc.compView = dc_Product.View.viewFront
            m_clsComp.m_dc.compName = devShape.Name
            m_clsComp.m_dc.compType = dc_Product.vnetType.ptPlatformWintel
            m_clsComp.m_dc.compSubtype = dc_Product.vnetSubtype.stWintelServer

            drTemp = m_clsComp.m_dt.NewRow
            m_clsComp.movePropertiesToDataRow(drTemp, m_clsComp.m_dc)
            m_clsComp.UpdateComponentProperties(devShape, drTemp)
            drTemp = Nothing

            m_clsNet.m_dc.initProperties()
            m_clsNet.UpdateNetworkProperties(devShape, Nothing, "addattr")
            devShape.Cells("prop.attrnetipaddress").FormulaU = _clsVisio.StringToFormulaForString("192.168.1.102")
            devShape.Cells("prop.attrnetnetworkname").FormulaU = _clsVisio.StringToFormulaForString(devShape.Name)


            '*******************************************************************
            ' then a Raid Array
            mstShape = stnDoc.Masters("RAID Array")
            devShape = drawingPage.Drop(mstShape, 0, 0)
            devShape.NameU = strRaidArray
            devShape.Name = strRaidArray
            devShape.Text = strRaidArray
            _clsVisio.deleteShapeData(devShape)

            InstallComponentInSlot(drawingPage, strRack, strRaidArray, 4)
            _clsVisio.addShapeToLayer(drawingPage, devShape, strLayer, 0)
            _clsVisio.AddStandardConnections(devShape)

            m_clsComp.m_dc.initProperties()
            m_clsComp.m_dc.compView = dc_Product.View.viewFront
            m_clsComp.m_dc.compName = devShape.Name
            m_clsComp.m_dc.compType = dc_Product.vnetType.ptPlatformWintel
            m_clsComp.m_dc.compSubtype = dc_Product.vnetSubtype.stWintelServer

            drTemp = m_clsComp.m_dt.NewRow
            m_clsComp.movePropertiesToDataRow(drTemp, m_clsComp.m_dc)
            m_clsComp.UpdateComponentProperties(devShape, drTemp)
            drTemp = Nothing


            m_clsNet.m_dc.initProperties()
            m_clsNet.UpdateNetworkProperties(devShape, Nothing, "addattr")
            devShape.Cells("prop.attrnetipaddress").FormulaU = _clsVisio.StringToFormulaForString("192.168.1.103")
            devShape.Cells("prop.attrnetnetworkname").FormulaU = _clsVisio.StringToFormulaForString(devShape.Name)

            ' so that the component shapes are captured and we
            ' can use the dictionary when we create links
            initPageDictionaries(drawingPage)

            '*******************************************************************
            ' add some communication links
            Dim arrUnique As New ArrayList
            Dim lkUnique As New stcUniqueLink
            initLkUnique(lkUnique)
            With lkUnique
                .NodeA = strFileSrv
                .NodeAPort = "right"
                .NodeB = strRouter
                .NodeBPort = "right"
                .SubType = dc_Link.enumLinkTypes.linkCopper
            End With
            arrUnique.Add(lkUnique)
            initLkUnique(lkUnique)
            With lkUnique
                .NodeA = strRouter
                .NodeAPort = "left"
                .NodeB = strAppSrv
                .NodeBPort = "left"
                .SubType = dc_Link.enumLinkTypes.linkFiber
            End With
            arrUnique.Add(lkUnique)

            ConnectNodeAToNodeB(drawingPage, arrUnique)

            PutOnLegend()


            '*******************************************************************
            ' clean up the picture

            Dim visWin As Microsoft.Office.Interop.Visio.Window = drawingApplication.ActiveWindow
            visWin.DeselectAll()
            drawingApplication.DoCmd(VisUICmds.visCmdViewFitInWindow)
            ' allow the system to act on selection changed events
            System.Windows.Forms.Application.DoEvents()

            initPageDictionaries(drawingPage)


        Catch com As COMException
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(com, "Com+ Policy")
            If (rethrow) Then
                Throw
            End If
        Catch err As Exception
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(err, "Log Only Policy")
            If (rethrow) Then
                Throw
            End If
        Finally

        End Try


    End Sub



#End Region

#Region " rack drawing helpers "

    '
    ' go through a generic rack and add connection point names so that
    ' we can address at a shelf level for the rack addin
    '
    Private Sub RenameRackShelfRows(ByVal visShape As Microsoft.Office.Interop.Visio.Shape)
        Dim visSection As Microsoft.Office.Interop.Visio.Section
        Dim visRow As Microsoft.Office.Interop.Visio.Row
        Dim strShelfName As String

        visSection = visShape.Section(VisSectionIndices.visSectionConnectionPts)

        Dim intX As Integer
        Dim intY As Integer
        Dim intShelf As Integer
        Dim rowName As String
        rowName = ""
        ' connections start at zero
        For intX = 0 To visSection.Count - 1
            visRow = visSection.Row(intX)
            strShelfName = "slot_"
            intY = (intX + 1) Mod 2 ' are we odd or even
            If intY = 0 Then
                intShelf = ((intX + 1) / 2)
                strShelfName = strShelfName & CStr(intShelf) & "_2"
            Else
                intShelf = (intX / 2) + 1
                strShelfName = strShelfName & CStr(intShelf) & "_1"
            End If
            visRow.NameU = strShelfName
            visRow.Name = strShelfName
        Next intX

    End Sub

    '
    ' considered colorbyvalue but did not get results we wanted
    '
    Private Sub AddNetworkLayersToPage _
            (ByVal Page As Microsoft.Office.Interop.Visio.Page)

        Dim pagCell As Microsoft.Office.Interop.Visio.Cell
        Dim layersObj As Microsoft.Office.Interop.Visio.Layers
        Dim layerObj As Microsoft.Office.Interop.Visio.Layer

        Try


            ' Add network status layers
            layersObj = Page.Layers

            layerObj = layersObj.Add(dc_Network.netStatus.netAvailable.ToString)
            pagCell = Page.PageSheet.Cells("layers.color[1]")
            _clsVisio.SetCellValueToString(pagCell, VisDefaultColors.visGreen)

            layerObj = layersObj.Add(dc_Network.netStatus.netUnavailable.ToString)
            pagCell = Page.PageSheet.Cells("layers.color[2]")
            _clsVisio.SetCellValueToString(pagCell, VisDefaultColors.visRed)

            layerObj = layersObj.Add(dc_Network.netStatus.netErrors.ToString)
            pagCell = Page.PageSheet.Cells("layers.color[3]")
            _clsVisio.SetCellValueToString(pagCell, VisDefaultColors.visYellow)

            layerObj = layersObj.Add(dc_Network.netStatus.netUndefined.ToString)
            pagCell = Page.PageSheet.Cells("layers.color[4]")
            _clsVisio.SetCellValueToString(pagCell, VisDefaultColors.visBlue)


            ' add cable layers
            ' this one gets added when we use a dynamic connector
            layerObj = layersObj.Add("Connector")
            pagCell = Page.PageSheet.Cells("layers.color[5]")
            pagCell.Formula = 255
            'unTerminated cable (we have one side but not the other)
            layerObj = layersObj.Add("UnTerminatedCables")
            pagCell = Page.PageSheet.Cells("layers.color[5]")
            pagCell.Formula = 255
            ' inside a rack
            layerObj = layersObj.Add("IntraRack")
            pagCell = Page.PageSheet.Cells("layers.color[5]")
            pagCell.Formula = 255
            'between racks
            layerObj = layersObj.Add("InterRack")
            pagCell = Page.PageSheet.Cells("layers.color[5]")
            pagCell.Formula = 255
            'between sites
            layerObj = layersObj.Add("Wan")
            pagCell = Page.PageSheet.Cells("layers.color[5]")
            pagCell.Formula = 255
            ' a layer for the cabinets
            layerObj = layersObj.Add("Cabinets")
            pagCell = Page.PageSheet.Cells("layers.color[5]")
            pagCell.Formula = 255

        Catch com As COMException
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(com, "Com+ Policy")
            If (rethrow) Then
                Throw
            End If
        Catch err As Exception
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(err, "Log Only Policy")
            If (rethrow) Then
                Throw
            End If
        Finally


        End Try


    End Sub

    '
    ' to support everything other than a rack as a component
    '
    Public Sub InstallComponentInSlot _
                        (ByVal drawingPage As Microsoft.Office.Interop.Visio.Page, _
                        ByVal strParent As String, _
                        ByVal strComponent As String, _
                        ByVal strSlot As String)


        Try

            Dim strTwo As String
            strTwo = "slot_" & strSlot & "_2"
            Dim strOne As String
            strOne = "slot_" & strSlot & "_1"

            InstallComponent1D(drawingPage, strComponent, strParent, strOne, strTwo)


        Catch com As COMException
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(com, "Com+ Policy")
            If (rethrow) Then
                Throw
            End If
        Catch err As Exception
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(err, "Log Only Policy")
            If (rethrow) Then
                Throw
            End If

        End Try

    End Sub

    '
    ' pass in the page, the parent component, the component to install, and
    ' two connection points, this is the base for installing components
    '
    Public Sub InstallComponent1D _
                        (ByVal drawingPage As Microsoft.Office.Interop.Visio.Page, _
                        ByVal strComponent As String, _
                        ByVal strParent As String, _
                        ByVal strParent_1 As String, _
                        ByVal strParent_2 As String)

        Dim visShapes As Microsoft.Office.Interop.Visio.Shapes
        Dim visComponent As Microsoft.Office.Interop.Visio.Shape = Nothing
        Dim visParent As Microsoft.Office.Interop.Visio.Shape = Nothing
        Dim visCell As Microsoft.Office.Interop.Visio.Cell

        Dim strBeginX As String
        Dim strEndX As String
        Dim strBeginY As String
        Dim strEndY As String
        Dim strConnection As String
        Dim blnInstallComponent As Boolean = True

        Try
            visShapes = drawingPage.Shapes
            Try
                visParent = visShapes.ItemU(strParent)
            Catch
            End Try

            If visParent Is Nothing Then
                MsgBox("InstallComponent1D (parent) " & strParent & " does not exist")
                blnInstallComponent = False
                GoTo ExitHandler
            End If

            Try
                visComponent = visShapes.ItemU(strComponent)
            Catch
            End Try

            If visComponent Is Nothing Then
                Debug.Print("InstallComponent1D (component) " & strComponent & " does not exist")
                blnInstallComponent = False
                GoTo ExitHandler
            End If

            strConnection = "Connections." & strParent_1
            If visParent.CellExists(strConnection, False) = False Then
                Debug.Print("connection (slot) one does not exist " & strParent_1 & " " & visParent.Name)
                blnInstallComponent = False
            End If
            strConnection = "Connections." & strParent_2
            If visParent.CellExists(strConnection, False) = False Then
                Debug.Print("connection (slot) two does not exist " & strParent_2 & " " & visParent.Name)
                blnInstallComponent = False
            End If

            ' build the cell formulas for connecting component to correct cabinet
            ' and shelf. Visio 12 gets confused with some names if they
            ' are not delimited by an appostrophe

            If blnInstallComponent = True Then

                strBeginX = "PAR(PNT('" & strParent & "'!Connections." & strParent_1 & ".X,'" & strParent & "'!Connections." & strParent_1 & ".Y))"
                strEndX = "PAR(PNT('" & strParent & "'!Connections." & strParent_2 & ".X,'" & strParent & "'!Connections." & strParent_2 & ".Y))"
                strBeginY = "PAR(PNT('" & strParent & "'!Connections." & strParent_1 & ".X,'" & strParent & "'!Connections." & strParent_1 & ".Y))"
                strEndY = "PAR(PNT('" & strParent & "'!Connections." & strParent_2 & ".X,'" & strParent & "'!Connections." & strParent_2 & ".Y))"


                If visComponent.CellExists("BeginX", False) = True Then
                    visCell = visComponent.Cells("BeginX")
                    visCell.Formula = strBeginX
                End If
                If visComponent.CellExists("EndX", False) = True Then
                    visCell = visComponent.Cells("EndX")
                    visCell.Formula = strEndX
                End If
                If visComponent.CellExists("BeginY", False) = True Then
                    visCell = visComponent.Cells("BeginY")
                    visCell.Formula = strBeginY
                End If
                If visComponent.CellExists("EndX", False) = True Then
                    visCell = visComponent.Cells("EndY")
                    visCell.Formula = strEndX
                End If

            End If


ExitHandler:
        Catch com As COMException
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(com, "Com+ Policy")
            If (rethrow) Then
                Throw
            End If
        Catch err As Exception
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(err, "Log Only Policy")
            If (rethrow) Then
                Throw
            End If

        End Try
    End Sub

    '
    '
    '
    Private Sub PutOnLegend()

        Try

            Dim docStencil As Microsoft.Office.Interop.Visio.Document
            Dim strStencilName As String = "periph_u.vss"
            Dim strMaster As String = "Legend"

            Dim vsoShape As Microsoft.Office.Interop.Visio.Shape
            Dim vsoPage As Microsoft.Office.Interop.Visio.Page = drawingPage

            vsoShape = _clsVisio.DropMasterOnPage(vsoPage, strMaster, strStencilName, 24, 24, VisUnitCodes.visInches)
            vsoShape.Name = "visLegend"
            vsoShape.NameU = "visLegend"
            vsoShape.Cells("PinX").Formula = "2ft"
            vsoShape.Cells("PinY").Formula = "3ft"

            ' since it has to be open, close it
            docStencil = drawingApplication.Documents(strStencilName)
            docStencil.Close()

        Catch com As COMException
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(com, "Com+ Policy")
            If (rethrow) Then
                Throw
            End If
        Catch err As Exception
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(err, "Log Only Policy")
            If (rethrow) Then
                Throw
            End If

        End Try

    End Sub

    '
    ' used for testing example drawings
    '
    Public Sub ConnectNodeAToNodeB _
                            (ByVal visPage As Microsoft.Office.Interop.Visio.Page, _
                            ByVal arrUniqueLinks As ArrayList)


        Dim objNodeA As Microsoft.Office.Interop.Visio.Shape
        Dim objNodeB As Microsoft.Office.Interop.Visio.Shape
        Dim objCell As Microsoft.Office.Interop.Visio.Cell
        Dim visCable As Microsoft.Office.Interop.Visio.Shape
        Dim intPos As Integer = 0
        Dim lkUnique As New stcUniqueLink
        Dim strNodeA As String = ""
        Dim strNodeB As String = ""

        Try


            Const BASIC_FLOWCHART_STENCIL As String = _
                "Basic Flowchart Shapes (US units).vss"
            Dim lclMaster As Microsoft.Office.Interop.Visio.Master = Nothing
            Try
                lclMaster = drawingDocument.Masters("Dynamic Connector")
            Catch
            End Try
            Dim mstrShape As Microsoft.Office.Interop.Visio.Shape
            If lclMaster Is Nothing Then
                Dim stnDoc As Microsoft.Office.Interop.Visio.Document = Me.drawingApplication.Documents.OpenEx(BASIC_FLOWCHART_STENCIL, VisOpenSaveArgs.visOpenDocked + VisOpenSaveArgs.visAddHidden)
                Dim visMaster As Microsoft.Office.Interop.Visio.Master = stnDoc.Masters("Dynamic Connector")
                mstrShape = visPage.Drop(visMaster, 0, 0)
                stnDoc.Close()
            Else
                mstrShape = visPage.Drop(lclMaster, 0, 0)
            End If


            If 0 < arrUniqueLinks.Count Then

                If m_dictComponents.Count = 0 Then initPageDictionaries(drawingPage)

                For intPos = 0 To arrUniqueLinks.Count - 1

                    With arrUniqueLinks.Item(intPos)
                        strNodeA = LCase(.nodea.ToString)
                        strNodeB = LCase(.nodeb.ToString)
                        ' do we have two valid shapes
                        objNodeA = Nothing
                        objNodeB = Nothing

                        ' first chase down the nodes
                        For Each kvp As KeyValuePair(Of Integer, String) In m_dictComponents
                            If LCase(kvp.Value) = LCase(strNodeA) Then
                                objNodeA = visPage.Shapes.ItemFromID(kvp.Key)
                                Exit For
                            End If
                        Next kvp
                        For Each kvp As KeyValuePair(Of Integer, String) In m_dictComponents
                            If LCase(kvp.Value) = LCase(strNodeB) Then
                                objNodeB = visPage.Shapes.ItemFromID(kvp.Key)
                                Exit For
                            End If
                        Next kvp
                        visCable = mstrShape.Duplicate

                        Dim strLabel As String = .NodeA & "." & .NodeAPort & " <=> " & .NodeB & "." & .NodeBPort
                        visCable.Text = strLabel

                        visCable.Cells("LineWeight").Formula = "1 pt"
                        visCable.Cells("BeginArrow").Formula = "10"
                        visCable.Cells("EndArrow").Formula = "10"
                        visCable.Cells("BeginArrowSize").Formula = "0"
                        visCable.Cells("EndArrowSize").Formula = "0"

                        _clsVisio.ForceShapeData(visCable, "linkvNetSubType", "", "attrNetworkLink")
                        ' need media length property for connection report
                        _clsVisio.ForceShapeData(visCable, "linkmediaLength", "", "attrNetworkLink")
                        _clsVisio.ForceShapeData(visCable, "linkName", strLabel, "attrNetworkLink")


                        '
                        ' consider extending to TIA 568-B for distances
                        ' http://www.siemon.com/us/standards/
                        ' This would make a good site validation tool
                        '
                        ' consider TIA 606 for documentation requirements
                        ' we do something of this with the infrastructure
                        ' module for creating node names (we include the cabinet name)

                        Dim strSub As String = CStr(.subtype)
                        '
                        Select Case .SubType
                            ' for fiber a red
                            Case enumLinkTypes.linkFiber
                                objCell = visCable.Cells("LineColor")
                                objCell.FormulaU = VisDefaultColors.visRed
                                _clsVisio.SetCustomPropertyValue(visCable, "linkvNetSubType", _
                                                    CStr(enumLinkTypes.linkFiber), _
                                                    VisUnitCodes.visUnitsString)
                                ' for copper use blue
                            Case enumLinkTypes.linkCopper
                                objCell = visCable.Cells("LineColor")
                                objCell.Formula = VisDefaultColors.visBlue
                                _clsVisio.SetCustomPropertyValue(visCable, "linkvNetSubType", _
                                                    CStr(enumLinkTypes.linkCopper), _
                                                    VisUnitCodes.visUnitsString)
                            Case Else
                                objCell = visCable.Cells("LineColor")
                                objCell.Formula = VisDefaultColors.visBlack
                                _clsVisio.SetCustomPropertyValue(visCable, "linkvNetSubType", _
                                                    CStr(.Type), _
                                                    VisUnitCodes.visUnitsString)
                        End Select

                        Dim strNodeAConn As String
                        Dim strNodeBConn As String
                        strNodeAConn = "connections." & .NodeAPort
                        strNodeBConn = "connections." & .NodeBPort

                        Dim objBeginX As Microsoft.Office.Interop.Visio.Cell
                        Dim objEndX As Microsoft.Office.Interop.Visio.Cell
                        Dim strError As String

                        objBeginX = visCable.CellsSRC( _
                                VisSectionIndices.visSectionObject, VisRowIndices.visRowXForm1D, VisCellIndices.vis1DBeginX)
                        If objNodeA.CellExists(strNodeAConn, False) = True Then
                            objBeginX.GlueTo(objNodeA.Cells(strNodeAConn))
                        Else
                            strError = "cannot find " & objNodeA.NameU.ToString _
                                        & "point " & strNodeAConn
                            MsgBox(strError)
                        End If

                        objEndX = visCable.CellsSRC( _
                            VisSectionIndices.visSectionObject, VisRowIndices.visRowXForm1D, VisCellIndices.vis1DEndX)
                        If objNodeB.CellExists(strNodeBConn, False) = True Then
                            objEndX.GlueTo(objNodeB.Cells(strNodeBConn))
                        Else
                            strError = "cannot find " & objNodeB.NameU.ToString _
                                        & "point " & strNodeBConn
                            MsgBox(strError)
                        End If

                    End With ' the current array position

                    System.Windows.Forms.Application.DoEvents()
                Next intPos


                ' get rid of the master shape
                mstrShape.Delete()


            Else
                ' passed an empty array
                Exit Sub
            End If

        Catch com As COMException
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(com, "Com+ Policy")
            If (rethrow) Then
                Throw
            End If
        Catch err As Exception
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(err, "Log Only Policy")
            If (rethrow) Then
                Throw
            End If
        Finally

        End Try

    End Sub

    ' 
    ' build two shapeid dictionaries for the passed in page, one for
    ' components and one for links.
    ' This routine allows us to search for shapes without having to
    ' continually cross the com+ boundary
    '
    Public Sub initPageDictionaries(ByVal visPage As Microsoft.Office.Interop.Visio.Page)


        Try

            If Not (m_dictComponents Is Nothing) Then
                m_dictComponents = Nothing
            End If
            m_dictComponents = New Dictionary(Of Integer, String)

            If Not (m_dictLinks Is Nothing) Then
                m_dictLinks = Nothing
            End If
            m_dictLinks = New Dictionary(Of Integer, String)

            Dim idShape As Integer
            Dim visShape As Microsoft.Office.Interop.Visio.Shape

            If Not (visPage Is Nothing) Then
                For Each visShape In visPage.Shapes

                    ' get the shapeID for our key in the dictionary 
                    idShape = visShape.ID
                    ' test to see if it is a link 
                    If visShape.CellExists("prop.linkName", False) = True Then
                        If m_dictLinks.ContainsKey(idShape) = False Then
                            m_dictLinks.Add(idShape, visShape.NameU)
                        End If
                    End If
                    If visShape.CellExists("prop.compName", False) = True Then
                        If m_dictComponents.ContainsKey(idShape) = False Then
                            m_dictComponents.Add(idShape, visShape.NameU)
                        End If
                    End If
                Next visShape
            End If

            'Debug.Print("dictionary counts " & dictComponents.Count & " " & dictLinks.Count)

        Catch com As COMException
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(com, "Com+ Policy")
            If (rethrow) Then
                Throw
            End If
        Catch err As Exception
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(err, "Log Only Policy")
            If (rethrow) Then
                Throw
            End If
        End Try

    End Sub




#End Region



End Class
